# $Id: $

=item Combinator

This is the root of the Visitor::Combinator class hierarchy. 

The Combinator classes support replacing elements by always returning a 
visitable node. By default, the return value is the node that was visited, but
a new node may be returned, including Undef (for delete).

Because of this use of the return value, an out-of-band success mechanism
is implemented using the C<.success> attribute. Shortcut methods <.PASS>
and C<.FAIL> are equivalent to C<.success(1)> and C<.success(0)>.

Note that the Combinator root class extends a HierarchyVisitor class
to inherit all the visit_XXX methods for individual subclasses.

=cut


module Visitor::Combinator;
# extends Slam::HierarchyVisitor

_ONLOAD();

sub _ONLOAD() {
	if our $onload_done { return 0; }
	$onload_done := 1;

	Parrot::IMPORT('Dumper', 'ASSERT DIE DUMP DUMP_ NOTE');
	
	my $class_name := 'Visitor::Combinator';
	NOTE("Creating class ", $class_name);
	Class::SUBCLASS($class_name, 
		'Class::HashBased');
	
	Class::multi_method($class_name, 'visit', :starting_with('_visit_'));
	
	NOTE("done");
}
method FAIL()			{ self.success(0); }
method PASS()			{ self.success(1); }

method success(*@value)		{ self._ATTR('success', @value); }

# Utility method hoisted from a lot of children.
method use_result_of($v, $node) {
	NOTE("Using results of visitor: ", $v);
	my $result := $v.visit($node);
	self.success($v.success);
	return $result;
}

method visit_default($node) {
	NOTE("Visitor ", ~self, " is visiting ", Class::name_of($node), 
		" node: ", $node);
	self._ABSTRACT_METHOD;
}

# NB: This list was generated by the class_hierarchy script in $/build, and
# should be maintained automatically by rules in the Makefile.

# class_hierarchy.pl BEGIN CONTENTS self.visit_default($node);

# This section automatically generated by austin at Tue Oct 20 01:55:22 2009 GMT

method _visit_Slam_Adverb($node)		{ self.visit_default($node); }
method _visit_Slam_Adverb_Flat($node)		{ self.visit_default($node); }
method _visit_Slam_Adverb_Multi($node)		{ self.visit_default($node); }
method _visit_Slam_Adverb_Named($node)		{ self.visit_default($node); }
method _visit_Slam_Adverb_Optional($node)	{ self.visit_default($node); }
method _visit_Slam_Adverb_RegisterClass($node)	{ self.visit_default($node); }
method _visit_Slam_Adverb_Slurpy($node)		{ self.visit_default($node); }
method _visit_Slam_Adverb_Vtable($node)		{ self.visit_default($node); }
method _visit_Slam_Error($node)			{ self.visit_default($node); }
method _visit_Slam_IncludeFile($node)		{ self.visit_default($node); }
method _visit_Slam_Literal_Float($node)		{ self.visit_default($node); }
method _visit_Slam_Literal_Integer($node)	{ self.visit_default($node); }
method _visit_Slam_Literal_String($node)	{ self.visit_default($node); }
method _visit_Slam_Lookups($node)		{ self.visit_default($node); }
method _visit_Slam_Message($node)		{ self.visit_default($node); }
method _visit_Slam_Mixin_HasType($node)		{ self.visit_default($node); }
method _visit_Slam_Scope_Function($node)	{ self.visit_default($node); }
method _visit_Slam_Scope_GlobalRoot($node)	{ self.visit_default($node); }
method _visit_Slam_Scope_HllRoot($node)		{ self.visit_default($node); }
method _visit_Slam_Scope_Local($node)		{ self.visit_default($node); }
method _visit_Slam_Scope_Namespace($node)	{ self.visit_default($node); }
method _visit_Slam_Scope_NamespaceDefinition($node) { self.visit_default($node); }
method _visit_Slam_Scope_Parameter($node)	{ self.visit_default($node); }
method _visit_Slam_Scope_Pervasive($node)	{ self.visit_default($node); }
method _visit_Slam_Statement_Null($node)	{ self.visit_default($node); }
method _visit_Slam_Statement_Return($node)	{ self.visit_default($node); }
method _visit_Slam_Statement_SymbolDeclarationList($node) { self.visit_default($node); }
method _visit_Slam_Statement_UsingNamespace($node) { self.visit_default($node); }
method _visit_Slam_Symbol_Declaration($node)	{ self.visit_default($node); }
method _visit_Slam_Symbol_Namespace($node)	{ self.visit_default($node); }
method _visit_Slam_Symbol_Reference($node)	{ self.visit_default($node); }
method _visit_Slam_Type_Array($node)		{ self.visit_default($node); }
method _visit_Slam_Type_Declarator($node)	{ self.visit_default($node); }
method _visit_Slam_Type_Function($node)		{ self.visit_default($node); }
method _visit_Slam_Type_Hash($node)		{ self.visit_default($node); }
method _visit_Slam_Type_MultiSub($node)		{ self.visit_default($node); }
method _visit_Slam_Type_Pointer($node)		{ self.visit_default($node); }
method _visit_Slam_Type_Specifier($node)	{ self.visit_default($node); }
method _visit_Slam_Warning($node)		{ self.visit_default($node); }

# class_hierarchy.pl END

# This only occurs once, and in the PastRewrite phase at that. So it gets 
# blocked by default in class_hierarchy.pl.
method _visit_Slam_Stmts($node)		{ self.visit_default($node); }
